/* 
 * File:   ClientHandler.cpp
 * Author: Lance
 * 
 * Created on September 30, 2012, 12:24 PM
 */

#include "ClientHandler.h"

ClientHandler::ClientHandler(int client_socket) {
	this->client_socket = client_socket;
	messageCenter = UserMessages::getSingleton();
	debug = false;
}

ClientHandler::ClientHandler(const ClientHandler& orig) {
}

ClientHandler::~ClientHandler() {
}

void ClientHandler::handle()
{
	while(handleRequests(client_socket))
	{
		
	}
	close(client_socket);
	
}

bool ClientHandler::handleRequests(int c)
{
	string message ("");

	char * buf = new char[1024];
	//short circuit... if they don't give us a command in the first for bytes, they aren't using the protocol right
	do
	{
		buf = readRequest(c);
		if(buf == NULL)
		{
			return false;
		}
		message += buf;
	} while (message.length() < 4);
	
	string command = stripCommand(&message);
	if (command.empty())
	{
		if(debug) cout << ("Invalid command! ", command);
		return false;
	}
	
//	if(debug)cout << ("Command: ", command);
//	if(debug)cout << ("--MSG START--");
//	if(debug)cout << (message.c_str());
//	if(debug)cout << ("--MSG END--");

	if(command.compare("list") == 0)
	{
		if(debug) cout << ("Responding to List");
		respondList(message);
	}
	else if(command.compare("put") == 0)
	{
//		if(debug)cout << ("Responding to put");
		respondPut(message);
	}
	else if(command.compare("get") == 0)
	{
		respondGet(message);
	}
	return true;
}

void ClientHandler::sendResponse(string response)
{
	if(debug)
		cout << "Sending: " << response << endl;
	const char * ptr = response.c_str();
	int nleft = response.length();
	int nwritten;
	while (nleft) {
		if ((nwritten = send(client_socket, ptr, nleft, 0)) < 0) {
			if (errno == EINTR) {
 				  // the socket call was interrupted -- try again
				continue;
			} else {
 				  // an error occurred, so break out
				perror("write");
				break;
			}
		} else if (nwritten == 0) {
			  // the socket is closed
			break;
		}
		nleft -= nwritten;
		ptr += nwritten;
	}
}

void ClientHandler::respondList(string message)
{
//	if(debug) cout << ("respond list");
	// make sure we have the whole command
	while (!containsNewLine(&message))
	{
		char * buf = new char[1024];
		buf = readRequest(client_socket);
		if (buf == NULL)
			return;
		message += readRequest(client_socket);
	}
	
	if (message.find_first_of(" ") != 0)
	{
//		if(debug)cout << ("bad list message");
		sendResponse("error Your client has a malformed list protocol\n");
		return;
	}
	message.erase(0,1);
	
	int end = message.find_first_of("\n");
	string user = message.substr(0, end);
//	if(debug) cout << ("User: ", user);
	vector<Message> messages = messageCenter->getUsersMessages(user);
//	if(debug)cout << ("message list size: ", messages.size());	
	if (messages.empty())
	{
		sendResponse("error no messages for this user\n");
		return;
	}

	int size = messages.size();
//	if(debug)cout << ("message list size: ", messages.size());
	string response;
	response = "list "+static_cast<ostringstream*>( &(ostringstream() << size) )->str() +"\n";
//	cout << messages[0].message;
	for (int i = 0; i < size; i++)
	{
		response += static_cast<ostringstream*>( &(ostringstream() << i+1) )->str();
		response += " " + messages[i].subject + "\n";
	}
//	if(debug)cout << ("Response: ", response);
	sendResponse(response);
}

void ClientHandler::respondPut(string message)
{
//	if(debug)cout << ("put response");
	while(!containsNewLine(&message))
	{
//		if(debug)cout << (message.c_str());
		char * buf = new char[1024];
		buf = readRequest(client_socket);
		if (buf == NULL)
			return;
		message += readRequest(client_socket);
	}

	if (message.find_first_of(" ") != 0)
	{
//		if(debug)cout << ("bad put message");
		sendResponse("error Your client has a malformed put protocol\n");
		return;
	}
	message.erase(0,1);

	int index = message.find_first_of(" ");
	if(index == -1)
	{
//		if(debug)cout << ("bad put message");
		sendResponse("error Your client has a malformed put protocol\n");
		return;

	}
	string user = message.substr(0, index);
	message.erase(0, index+1);
	index = message.find_first_of(" ");
	if (index == -1)
	{
//		if(debug)cout << ("bad put message");
		sendResponse("error Your client has a malformed put protocol\n");
		return;		
	}
	string subject = message.substr(0, index);
	message.erase(0, index+1);
	index = message.find_first_of("\n");
	if (index == -1)
	{
//		if(debug)cout << ("bad put message");
		sendResponse("error Your client has a malformed put protocol\n");
		return;		
	}
	int length = atoi(message.substr(0, index).c_str());
	message.erase(0,index+1);
	
	string messageStr;
	const char * ptr = message.c_str();
	for (int i = 0; i < length; i++, ptr++)
	{
		if(ptr == '\0')
		{
//			if(debug)cout << ("get more of the message");
			ptr = readRequest(client_socket);
		}
		messageStr += *ptr;
	}
//	if(debug)cout << ("Message: ", messageStr);	

	
	Message userMessage;
	userMessage.subject = subject;
	userMessage.message = messageStr;
	messageCenter->putUserMessage(user, userMessage);//userMessages[user] = messages;
	sendResponse("OK\n");
//	if(debug)cout << ("got here");
	
}

void ClientHandler::respondGet(string message)
{
//	if(debug)cout << ("respondGet");
	while(!containsNewLine(&message))
	{
		char * buf = new char[1024];
		buf = readRequest(client_socket);
		if (buf == NULL)
			return;
		message += readRequest(client_socket);
	}

	int delim = message.find_first_of(" ");
	if(delim != 0)
	{
//		if(debug)cout << ("bad get message");
		sendResponse("error Your client has a malformed get protocol");
		return;
	}
	message.erase(0,1);
	delim = message.find_first_of(" ");
	if (delim == -1)	
	{
//		if(debug)cout << ("bad put message");
		sendResponse("error Your client has a malformed get protocol\n");
		return;
	}
	string user = message.substr(0, delim);
	message.erase(0, delim+1);
	delim = message.find_first_of("\n");
	if (delim == -1)
	{
//		if(debug)cout << ("bad put message");
		sendResponse("error Your client has a malformed get protocol\n");
		return;
	}
	
	int index = atoi(message.substr(0,delim).c_str() )-1;
	vector<Message> messages = messageCenter->getUsersMessages(user);
	if (messages.empty() || messages.size() <= index)
	{
		sendResponse("error No message at that index for this user\n");
		return;
	}
	string returnMessage = messages[index].message;

	string length = static_cast<ostringstream*>( &(ostringstream() << returnMessage.size()) )->str();
	string response = "message " + messages[index].subject + " " + length + "\n" + returnMessage;
	sendResponse(response);
}

bool ClientHandler::containsNewLine(string * str)
{
	return (str->find("\n") != -1);
}

string ClientHandler::stripCommand(string * command)
{
	if (command->find_first_of("put") == 0)
	{
		command->erase(0,3);
		return "put";
	}
	if (command->find_first_of("list") == 0)
	{
		command->erase(0,4);
		return "list";
	}
	if (command->find_first_of("get") == 0)
	{
		command->erase(0,3);
		return "get";

	}
	return "";
}

char * ClientHandler::readRequest(int c, bool recursive)
{
	int nread;
	// read a request
	char * buf = new char[1024];
	memset(buf,0,1024);
	nread = recv(c,buf,1024,0);
	if (nread < 0) {
		if (errno == EINTR)
		{
			if(recursive)
				return NULL;
	 		 // the socket call was interrupted -- try again /booh recursive
			buf = readRequest(c, true);
		}
		else
			// an error occurred, so break out
			return NULL;
	} else if (nread == 0) {
		  // the socket is closed
		return NULL;;
	}
//	if(debug)cout << ("nread: ", nread);
//	if(debug)cout << ("command length: ", strlen(buf));
	return buf;
}

char * ClientHandler::readRequest(int c)
{
	readRequest(c, false);
}